﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharpHomeEngine;
using System.Timers;

namespace ControllerTest
{


    public class TestController : Controller
    {
        Insteon.InsteonInterface Insteon;
        TagDigital KitchenSwitch; //
        TagDigital LivingRoomSwitch; //
        TagInt32 LivingRoomDimmer; //
        TagByte LampLincDimmer;
        TagBoolean LampLincOn;
        TagBoolean TriggerLincOpened;
        TagBoolean Motion1;
        TagBoolean Motion2;
        TagBoolean DeckLightOn;
        TagByte DeckLightDimmer;
        
        Timer DeckTimer = new Timer();
        Timer DeckLockoutTimer = new Timer();

        public TestController(StateEngine Engine, String Name) : base(Engine, Name)
        {
            Engine.StateChangesCompleted += new TagStateChangesCompletedDelegate(Engine_StateChangesCompleted);
            Engine.StateChange += new TagStateChangeDelegate(Engine_StateChange);
            Engine.DeviceEvent += new DeviceEventDelegate(Engine_DeviceEvent);
            DeckTimer.Elapsed += new ElapsedEventHandler(DeckTimer_Elapsed);
            DeckLockoutTimer.Elapsed += new ElapsedEventHandler(DeckLockoutTimer_Elapsed);
        }

        void Engine_DeviceEvent(Device Device, string Event, Tag Tag, object Value)
        {
            Console.WriteLine("################ {0} EVENT {1} {2} {3} {4}", DateTime.Now.ToString("HHmmss"), Device, Event, Tag, Value);
            if (Tag != null)
            {
                if (Tag == DeckLightOn && Event == "fast off") 
                { 
                    if (DeckLockoutTimer.Enabled) // enable motion sensor
                    {
                        DeckLockoutTimer.Stop();
                        SetSync(DeckLightDimmer, 0xFF);
                        SetSync(DeckLightDimmer, 0x00);
                    } else {// disable motion sensor
                        DeckLockoutTimer.Interval = 20 * 60 * 1000;
                        DeckLockoutTimer.AutoReset = false;
                        DeckLockoutTimer.Start();
                    }
                }
            }
        }

        void DeckLockoutTimer_Elapsed(object sender, ElapsedEventArgs e)
        {

        }

        void DeckTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            Console.WriteLine("################ {0} DeckTimer Elapsed", DateTime.Now.ToString("HHmmss"));
            if (Motion1.Value == true)
            {
                //keep on timing
                DeckTimer.Interval = 20000;
                DeckTimer.AutoReset = false;
                DeckTimer.Start();                
            }
            else
            {
                //Turn off decklight;
                SetSync(DeckLightOn, false);
            }
        }


        void Engine_StateChange(IChangeSource Source, long Handle, Tag Tag, object Value)
        {
            
            if (Tag == Motion1)
            {
                Console.WriteLine("############# {0} DeckTimer = {1} DeckLockoutTimer = {2} Motion", DateTime.Now.ToString("HHmmss"), DeckTimer.Enabled, DeckLockoutTimer.Enabled);
                if (Motion1.Value == true)
                {
                    if (DeckLockoutTimer.Enabled == false) //if i locked out the decklight then do not turn on the light due to motion.
                    {
                        SetSync(DeckLightDimmer, 0xFF);
                        DeckTimer.Interval = 120000;
                        DeckTimer.AutoReset = false;
                        DeckTimer.Start();
                        Console.WriteLine("################ {0} - DeckTimer.Interval = {1}", DateTime.Now.ToString("HHmmss"), DeckTimer.Interval);
                    }
                }
            }
        }

        void Engine_StateChangesCompleted(Request4TagStateChange Request)
        {
            //you dont HAVE to do anything with this. but if your doing Async requests then this could be useful.
            //Console.WriteLine("{0:0000} Engine_StateChangesAsyncCompleted", Request.ID);
        }



        public override void Init()
        {
            Insteon = (Insteon.InsteonInterface)StateEngine.GetDeviceInterface("Insteon1");
            KitchenSwitch = (TagDigital) StateEngine.GetTagByAddress("TestInterface.KitchenSwitch.Switch");
            LivingRoomSwitch = (TagDigital)StateEngine.GetTagByAddress("TestInterface.LivingRoomDimmer.Switch");
            LivingRoomDimmer = (TagInt32)StateEngine.GetTagByAddress("TestInterface.LivingRoomDimmer.Dimmer");
            LampLincDimmer = (TagByte)StateEngine.GetTagByAddress("Insteon1.LampLinc.Dimmer");
            LampLincOn = (TagBoolean)StateEngine.GetTagByAddress("Insteon1.LampLinc.On");
            TriggerLincOpened = (TagBoolean)StateEngine.GetTagByAddress("Insteon1.TriggerLinc.Opened");
            Motion1 = (TagBoolean)StateEngine.GetTagByAddress("Insteon1.MotionSensor1.Motion");
            Motion2 = (TagBoolean)StateEngine.GetTagByAddress("Insteon1.MotionSensor2.Motion");
            DeckLightDimmer = (TagByte)StateEngine.GetTagByAddress("Insteon1.DeckLight.Dimmer");
            DeckLightOn = (TagBoolean)StateEngine.GetTagByAddress("Insteon1.DeckLight.On");
        }

        public override void Execute()
        {
            ////plaing with linking below. Still havent got it to work 100%

            ////lets start off with a hig dimmer
            //SetSync(LampLincDimmer, (byte)0xF0);

            ////tell the modem to enter linking mode as a controller, group 3
            //Execute(new Insteon.Requests.StartAllLinking(this, Insteon, global::Insteon.LinkCode.Codes.IMController, 0x03));
            ////now "press the button" on the LampLink by sending this command, group 3
            //Execute(new Insteon.Requests.EnterLinkingMode(this, Insteon, (Insteon.InsteonDevice)LampLincDimmer.Device, 0x03));

            ////now set the lamplink to the level you want
            //SetSync(LampLincDimmer, (byte)0xF0);

            ////send the all link command to group 3. 0x11 = on. this should do it.
            //Execute(new Insteon.Requests.AllLinkCommand(this, Insteon, 0x03, 0x11));

            ////now we still need state changes from the lamplinc to "press the button" again, by sending this command. Group 1
            //Execute(new Insteon.Requests.EnterLinkingMode(this, Insteon, (Insteon.InsteonDevice)LampLincDimmer.Device, 0x01));
            ////now tell the modem to be a slave(group 1)
            //Execute(new Insteon.Requests.StartAllLinking(this, Insteon, global::Insteon.LinkCode.Codes.IMSlave, 0x01));

            //Console.WriteLine("Linked Dimmer = {0}", GetSync(LampLincDimmer));

            ////linking should be done in theory, turn off the lamplinc
            //SetSync(LampLincDimmer, (byte)0x00);
            //SetSync(LampLincDimmer, (byte)0xFF);
            //SetSync(LampLincDimmer, (byte)0x00);

            ////send the all link command to group 3. 0x11 = on.
            ////Execute(new Insteon.Requests.AllLinkCommand(this, Insteon, 0x03, 0x11));
            ////query the lamplinc to make sure its at the right level.
            //Console.WriteLine("Linked Dimmer = {0}", GetSync(LampLincDimmer));
            //Console.WriteLine("Linked Dimmer = {0}", GetSync(LampLincDimmer));
            //Console.WriteLine("Linked Dimmer = {0}", GetSync(LampLincDimmer));
            //Console.WriteLine("Linked Dimmer = {0}", GetSync(LampLincDimmer));

            //Console.WriteLine("TriggerLinc Opened = {0}", GetSync(TriggerLincOpened));

        }
    }
}
